package org.yaac.client;

import java.util.Date;

import javax.inject.Inject;
import javax.inject.Named;

import org.yaac.client.conf.BindingConstants;
import org.yaac.client.ui.MenuTreeViewModel;

import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Application shell for Yaac
 * 
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
public class YaacShell extends ResizeComposite {

	interface YaacShellUiBinder extends UiBinder<Widget, YaacShell> {}

	private static YaacShellUiBinder uiBinder = GWT.create(YaacShellUiBinder.class);

	/**
	 * The panel that holds menu
	 */
	@UiField
	SimpleLayoutPanel menuPanel;
	
	/**
	 * The panel that holds the content.
	 */
	@UiField
	SimpleLayoutPanel contentPanel;
	
	/**
	 * The container around the links at the top of the app.
	 */
	@UiField
	TableElement linkCell;

	/**
	 * A drop box used to change the locale.
	 */
	@UiField
	ListBox localeBox;

	/**
	 * The container around locale selection.
	 */
	@UiField
	TableCellElement localeSelectionCell;

	/**
	 * @param placeController global placeController
	 * @param mainActivityManager main activityManager
	 * @param treeModel main menu
	 * @param images
	 */
	@Inject
	public YaacShell(
			PlaceController placeController,
			@Named(BindingConstants.MENU_ACTIVITY_MANAGER) ActivityManager menuActivityManager,
			@Named(BindingConstants.MAIN_ACTIVITY_MANAGER) ActivityManager mainActivityManager, 
			MenuTreeViewModel treeModel, 
			YaacResources images) {		
		// Inject global styles.
		images.css().ensureInjected();
		
		// Initialize the ui binder.
		initWidget(uiBinder.createAndBindUi(this));
		initializeLocaleBox();

		// In RTL mode, we need to set some attributes.
		if (LocaleInfo.getCurrentLocale().isRTL()) {
			localeSelectionCell.setAlign("left");
			linkCell.setPropertyString("align", "left");
		}

		// use menu activity manager to manage the menu panel
		menuPanel.ensureDebugId("menuPanel");
		menuActivityManager.setDisplay(menuPanel);
		
		// use main activity manager to manage the main panel
		contentPanel.ensureDebugId("contentPanel");		
		mainActivityManager.setDisplay(contentPanel);
	}

	/**
	 * Initialize the {@link ListBox} used for locale selection.
	 */
	private void initializeLocaleBox() {
		final String cookieName = LocaleInfo.getLocaleCookieName();
		final String queryParam = LocaleInfo.getLocaleQueryParam();
		if (cookieName == null && queryParam == null) {
			// if there is no way for us to affect the locale, don't show the
			// selector
			localeSelectionCell.getStyle().setDisplay(Display.NONE);
			return;
		}
		String currentLocale = LocaleInfo.getCurrentLocale().getLocaleName();
		if (currentLocale.equals("default")) {
			currentLocale = "en";
		}
		String[] localeNames = LocaleInfo.getAvailableLocaleNames();
		for (String localeName : localeNames) {
			if (!localeName.equals("default")) {
				String nativeName = LocaleInfo.getLocaleNativeDisplayName(localeName);
				localeBox.addItem(nativeName, localeName);
				if (localeName.equals(currentLocale)) {
					localeBox.setSelectedIndex(localeBox.getItemCount() - 1);
				}
			}
		}
		localeBox.addChangeHandler(new ChangeHandler() {
			@SuppressWarnings("deprecation")
			public void onChange(ChangeEvent event) {
				String localeName = localeBox.getValue(localeBox.getSelectedIndex());
				if (cookieName != null) {
					// expire in one year
					Date expires = new Date();
					expires.setYear(expires.getYear() + 1);
					Cookies.setCookie(cookieName, localeName, expires);
				}
				if (queryParam != null) {
					UrlBuilder builder = Location.createUrlBuilder().setParameter(queryParam, localeName);
					Window.Location.replace(builder.buildString());
				} else {
					// If we are using only cookies, just reload
					Window.Location.reload();
				}
			}
		});
	}
}
